package com.pokermind.dse.tcp;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;

/**
 * PokerMind Decision Support Engine TCP Application 基于Netty的高性能TCP服务器，提供JSON协议API
 *
 * 技术特性: - 基于Spring Boot + Netty架构 - JSON字符串协议 (UTF-8编码) - 长连接复用，支持高并发 - 与DSE HTTP服务共享业务逻辑 - 完整的监控和指标体系 - 专业级错误处理和优雅关闭
 *
 * @author PokerMind Team
 */
@SpringBootApplication
@ComponentScan(basePackages = {"com.pokermind"})
public class DseTcpApplication {

    private static final Logger logger = LoggerFactory.getLogger(DseTcpApplication.class);

    public static void main(String[] args) {
        try {
            logger.info("Starting PokerMind DSE TCP Service...");
            // 配置Netty系统属性
            configureNettyProperties();
            // 创建Spring应用，设置为非Web应用程序
            SpringApplication app = new SpringApplication(DseTcpApplication.class);
            app.setWebApplicationType(org.springframework.boot.WebApplicationType.NONE);
            ConfigurableApplicationContext context = app.run(args);
            // 输出启动信息
            logStartupInfo(context);
            // 注册优雅关闭钩子
            registerShutdownHook(context);
        } catch (Exception e) {
            logger.error("Failed to start PokerMind DSE TCP Service: {}", e.getMessage(), e);
            System.exit(1);
        }
    }

    /**
     * 配置Netty性能优化参数
     */
    private static void configureNettyProperties() {
        // 设置Netty工作目录
        System.setProperty("io.netty.native.workdir", System.getProperty("java.io.tmpdir"));

        // 根据环境配置内存泄漏检测
        String profiles = System.getProperty("spring.profiles.active", "");
        if (profiles.contains("dev") || profiles.contains("test")) {
            System.setProperty("io.netty.leakDetection.level", "ADVANCED");
        } else {
            System.setProperty("io.netty.leakDetection.level", "SIMPLE");
        }

        // 使用池化分配器
        System.setProperty("io.netty.allocator.type", "pooled");
        System.setProperty("io.netty.allocator.directMemoryCacheAlignment", "64");

        // 设置EventLoop线程数 (CPU核数 * 2)
        int processors = Runtime.getRuntime().availableProcessors();
        System.setProperty("io.netty.eventLoopThreads", String.valueOf(processors * 2));

        logger.info("Netty properties configured - processors: {}, eventLoopThreads: {}", processors, processors * 2);
    }

    /**
     * 输出启动信息
     */
    private static void logStartupInfo(ConfigurableApplicationContext context) {
        String[] profiles = context.getEnvironment().getActiveProfiles();
        long pid = ProcessHandle.current().pid();
        String tcpHost = context.getEnvironment().getProperty("pokermind.tcp.server.host", "127.0.0.1");
        String tcpPort = context.getEnvironment().getProperty("pokermind.tcp.server.port", "8889");
        int processors = Runtime.getRuntime().availableProcessors();

        String startupInfo = String.format(
            "\n" + "========================================\n" + "  PokerMind DSE TCP Service Started\n" + "========================================\n" + "  Protocol: JSON over Binary Frame\n" + "  Framework: Spring Boot + Netty\n" + "  TCP Address: %s:%s\n" + "  Profiles: %s\n" + "  PID: %d\n" + "  JVM: %s\n" + "  CPU Cores: %d\n" + "  EventLoop Threads: %d\n" + "  Leak Detection: %s\n" + "========================================",
            tcpHost, tcpPort, profiles.length > 0 ? String.join(",", profiles) : "default", pid,
            System.getProperty("java.version"), processors, processors * 2,
            System.getProperty("io.netty.leakDetection.level", "SIMPLE"));

        logger.info(startupInfo);

        // 输出详细的配置信息（DEBUG级别）
        if (logger.isDebugEnabled()) {
            logDetailedConfiguration(context);
        }
    }

    /**
     * 输出详细配置信息（DEBUG级别）
     */
    private static void logDetailedConfiguration(ConfigurableApplicationContext context) {
        logger.debug("=== TCP Server Configuration ===");
        logger.debug("Host: {}", context.getEnvironment().getProperty("pokermind.tcp.server.host"));
        logger.debug("Port: {}", context.getEnvironment().getProperty("pokermind.tcp.server.port"));
        logger.debug("Boss Threads: {}", context.getEnvironment().getProperty("pokermind.tcp.server.boss-threads"));
        logger.debug("Worker Threads: {}", context.getEnvironment().getProperty("pokermind.tcp.server.worker-threads"));
        logger.debug("Max Connections: {}",
            context.getEnvironment().getProperty("pokermind.tcp.server.max-connections"));
        logger.debug("Read Timeout: {}s", context.getEnvironment().getProperty("pokermind.tcp.protocol.read-timeout"));
        logger.debug("Write Timeout: {}s",
            context.getEnvironment().getProperty("pokermind.tcp.protocol.write-timeout"));
        logger.debug("Enable Epoll: {}",
            context.getEnvironment().getProperty("pokermind.tcp.performance.enable-epoll"));
        logger.debug("Allocator Type: {}",
            context.getEnvironment().getProperty("pokermind.tcp.performance.allocator-type"));
        logger.debug("=== End Configuration ===");
    }

    /**
     * 注册优雅关闭钩子
     */
    private static void registerShutdownHook(ConfigurableApplicationContext context) {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            logger.info("Shutting down PokerMind DSE TCP Service gracefully...");
            try {
                context.close();
                logger.info("PokerMind DSE TCP Service shutdown completed.");
            } catch (Exception e) {
                logger.error("Error during shutdown: {}", e.getMessage(), e);
            }
        }, "shutdown-hook"));
    }
}
